﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace Common.Framework.Core.Jwt
{
    /// <summary>
    /// 
    /// </summary>
    public static class JwtExtension
    {
        /// <summary>
        /// 添加Jwt, 配置Jwt的验证
        /// </summary>
        /// <param name="services"></param>
        /// <param name="Configuration"></param>
        public static void AddJwtBearer(this IServiceCollection services, IConfiguration Configuration)
        {
            services.AddSingleton<JwtConfiguration>();//Jwt auth 控制

            // configure jwt authentication
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                //当验证失败时，回应标头会包含 WWW-Authenticate 标头，这裡会显示失败的详细错误原因
                options.IncludeErrorDetails = true; // 预设值为 true，有时会特别关闭

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // 透过这项宣告，就可以从 "sub" 取值并设定给 User.Identity.Name
                    NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
                    // 透过这项宣告，就可以从 "roles" 取值，并可让 [Authorize] 判断角色
                    RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",

                    // 一般我们都会验证 Issuer. 发行者
                    ValidateIssuer = true,
                    ValidIssuer = Configuration.GetValue<string>("JwtSettings:Issuer"),

                    // 通常不太需要验证 Audience
                    ValidateAudience = false,
                    //ValidAudience = "JwtAuthDemo", // 不验证就不需要填写

                    // 一般我们都会验证 Token 的有效期间
                    ValidateLifetime = true,

                    // 如果 Token 中包含 key 才需要验证，一般都只有签名而已
                    ValidateIssuerSigningKey = true,

                    // "签名key" 应该从 IConfiguration 取得
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue<string>("JwtSettings:SignKey")))
                };
            });
        }
    }
}
